/**
 *******************************************************************************
 * @FileName  : user_main.c
 * @Author    : GaoQiu
 * @CreateDate: 2020-05-18
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */
#include "user_main.h"
#include "utils/soft_uart.h"
#include "utils/mdc.h"
#include "utils/pool_buf.h"
#include "utils/msg.h"
#include "utils/stimer.h"
#include "utils/math.h"
#include "utils/heap.h"
#include "utils/lg_mem.h"
#include "utils/pm.h"

#include "stack/controller/ll_api.h"
#include "stack/controller/bb_api.h"
#include "stack/hci_defs.h"

#include "stack/host/dm_api.h"
#include "stack/host/l2cap_api.h"
#include "stack/host/att_api.h"
#include "stack/host/smp_api.h"

#include "profile/svc_handle.h"
#include "component/kv/kv_api.h"
#include "bsp/bsp.h"

/*!< Heap Size */
#define APP_HEAP_MEM_SIZE       (13 * 1024)
static uint32_t heap[APP_HEAP_MEM_SIZE/sizeof(uint32_t)] = {0};

#define APP_PM_EN               0

/*!< LED blink period Unit:ms */
#define APP_LED_EN              1
#define LED_BLINK_PERIOD        1000

/*! Connection parameter configuration */
#define APP_MAX_MST_NUM         0
#define APP_MAX_SLV_NUM         1
#define APP_MAX_CONN_NUM        (APP_MAX_MST_NUM + APP_MAX_SLV_NUM)

#define APP_ADV_EVT_TYPE        DM_ADV_CONN_UNDIRECT
#define APP_ADV_INTR_MIN        ADV_INTR_30_MS
#define APP_ADV_INTR_MAX        ADV_INTR_35_MS
#define APP_ADV_CHN             LL_ADV_CHAN_ALL
#define APP_ADV_FILT            LL_ADV_FILTER_NONE
#define APP_ADV_LOCAL_ADDR_TYPE LL_ADDR_PUBLIC
#define APP_ADV_PEER_ADDR_TYPE  LL_ADDR_PUBLIC
#define APP_ADV_PEER_ADDR       NULL

#define APP_L2C_CONN_UPD_TO     5  //unit:sec


/*! Link layer config. */
const LlCfg_t llCfg = {
	versNr    : LL_VER_BT_CORE_SPEC, /*!< BLE Core version.           */
	compId    : LL_COMPANY_ID,       /*!< Company ID.                 */
	subVersNr : LL_SUB_VERSION_NUM,  /*!< Implementation version.     */

	wlNum     : 0,                   /*!< White-list size.            */
	rlNum     : 0,                   /*!< Resolve list size.          */

	numAdvSet         : 0,
	extAdvDataLen     : 0,
	extScanRspDataLen : 0,
	advMargin         : 0,             /*!< unit:ms */

	maxMst    : APP_MAX_MST_NUM,     /*!< Max number of  master connection. */
	maxSlv    : APP_MAX_SLV_NUM,     /*!< Max number of  slave connection. */
	maxAclLen : 251,                 /*!< Length of ACL data.         */
	numRxBufs : 16,                  /*!< Number of Rx buffer.        */
	numTxBufs : 16,                  /*!< Number of Tx buffer.        */
	localSCA  : 300,                 /*!< Local sleep clock accuracy. */

	mstMargin : 5,                   /*! Master connection margin. Unit: 0.625ms*/
	numMoreDat: 32,                  /*! the max number of more data. Range: >1. */

	authPyldTimeoutEn: false,
};

/******************************************************************************/
/* Connection Manager                                                         */
/******************************************************************************/
typedef struct{
	uint32_t        connStartTick;
	uint16_t        connHandle;
	uint8_t         role;
	uint8_t         inUse;
	uint8_t         isSmpCmpl;

	MdcTimer_t      phyUpdTimer;
	MdcTimer_t      dleUpdTimer;
	MdcTimer_t      connUpdTimer;
}AppCCB_t;

/*! Application main control block. */
typedef struct{
	AppCCB_t        ccb[APP_MAX_CONN_NUM];
	MdcTimer_t      timer;
	MdcHandlerId_t  handlerId;
}AppCb_t;

AppCb_t appCb;

AppCCB_t *APP_AllocCcb(uint16_t connHandle, uint8_t role)
{
	AppCCB_t *pCcb = appCb.ccb;

	for(int i=0; i<COUNTOF(appCb.ccb); i++, pCcb++)
	{
		if(pCcb->inUse == false){
			pCcb->inUse = true;
			pCcb->connHandle = connHandle;
			pCcb->role = role;

			/* Start PHY Update Timer*/
			MDC_TimerConfigEx(&pCcb->phyUpdTimer, appCb.handlerId, APP_EVT_PHY_UPD, 0, connHandle);
			MDC_TimerStartMs(&pCcb->phyUpdTimer, 500);

			/* Start DLE Update Timer*/
			MDC_TimerConfigEx(&pCcb->dleUpdTimer, appCb.handlerId, APP_EVT_DLE_UPD, 0, connHandle);
			MDC_TimerStartMs(&pCcb->dleUpdTimer, 1000);

			/* Start Connection Update Timer*/
			MDC_TimerConfigEx(&pCcb->connUpdTimer, appCb.handlerId, APP_EVT_CONN_UPD, 0, connHandle);
			MDC_TimerStartMs(&pCcb->connUpdTimer, 4000);

			return pCcb;
		}
	}
	return NULL;
}

void APP_ReleaseCcbByHandle(uint16_t connHandle)
{
	AppCCB_t *pCcb = appCb.ccb;

	for(int i=0; i<COUNTOF(appCb.ccb); i++, pCcb++)
	{
		if(pCcb->connHandle == connHandle && pCcb->inUse){
			pCcb->inUse = false;
			MDC_TimerStop(&pCcb->phyUpdTimer);
			MDC_TimerStop(&pCcb->dleUpdTimer);
			MDC_TimerStop(&pCcb->connUpdTimer);
			return;
		}
	}
}

AppCCB_t *APP_GetConnCb(uint16_t connHandle)
{
	AppCCB_t *pCcb = appCb.ccb;

	for(int i=0; i<COUNTOF(appCb.ccb); i++, pCcb++)
	{
		if(pCcb->connHandle == connHandle && pCcb->inUse){
			return pCcb;
		}
	}
	return NULL;
}

void APP_MsgHandler(MdcEventMask_t event, MdcMsgHdr_t *pMsg)
{
	if(pMsg)
	{
		switch(pMsg->event)
		{
		case APP_EVT_UPD_ADV_DATA:
			BSP_LedToggle(LED_BLUE_PIN);
			MDC_TimerStartMs(&appCb.timer, LED_BLINK_PERIOD);
			break;

		case APP_EVT_DISCONN:
			break;

		case APP_EVT_PHY_UPD:
		{
			uint16_t connHandle = pMsg->param;
			UNUSED(connHandle);

			//LL_LE_SetPhy(connHandle, 0x00, LL_PHYS_LE_1M_BIT, LL_PHYS_LE_1M_BIT, LL_PHY_OPTIONS_NONE);
			//LL_LE_SetPhy(connHandle, 0x00, LL_PHYS_LE_2M_BIT, LL_PHYS_LE_2M_BIT, LL_PHY_OPTIONS_NONE);
			//LL_LE_SetPhy(connHandle, 0x00, LL_PHYS_LE_CODED_BIT, LL_PHYS_LE_CODED_BIT, LL_PHY_OPTIONS_S8_PREFERRED);
			//LL_LE_SetPhy(connHandle, 0x00, LL_PHYS_LE_CODED_BIT, LL_PHYS_LE_CODED_BIT, LL_PHY_OPTIONS_S2_PREFERRED);
			//LL_LE_SetPhy(connHandle, 0x00, LL_PHYS_LE_1M_BIT|LL_PHYS_LE_2M_BIT, LL_PHYS_LE_1M_BIT|LL_PHYS_LE_2M_BIT, LL_PHY_OPTIONS_NONE);
			//APP_TRACK_WRN("Start PHY Upd...\r\n");
			break;
		}
		case APP_EVT_DLE_UPD:
		{
			uint16_t connHandle = pMsg->param;
			UNUSED(connHandle);

			//HCI_LE_SetDataLen(connHandle, llCfg.maxAclLen, LL_MAX_TX_RX_TIME_1M(llCfg.maxAclLen));
			//APP_TRACK_WRN("Start DLE Upd...\r\n");
			break;
		}
		case APP_EVT_CONN_UPD:
		{
		#if APP_PM_EN
			L2C_SlvConnUpdateReq(pMsg->param, CONN_INTR_10_MS, CONN_INTR_10_MS, 99, 400);
			APP_TRACK_WRN("Start Connection Upd...\r\n");
		#endif
			break;
		}

		default:
			break;
		}
	}

	if(event)
	{
	}
}

void App_SendKeyReport(uint16_t attHandle, uint8_t *pData, uint32_t len)
{
	AppCCB_t *pCcb = appCb.ccb;
	for(int i=0; i<APP_MAX_CONN_NUM; i++, pCcb++)
	{
		if(pCcb->inUse){
			ATTS_ValueNotify(pCcb->connHandle, attHandle, pData, len);
		}
	}
}

void APP_DisconnectAll(void)
{
	AppCCB_t *pCcb = appCb.ccb;
	for(int i=0; i<COUNTOF(appCb.ccb); i++, pCcb++)
	{
		if(pCcb->inUse){
			HCI_Disconnect(pCcb->connHandle, HCI_ERR_REMOTE_USER_TERM_CONN);
		}
	}
}

/******************************************************************************/
/* Key                                                                        */
/******************************************************************************/
static uint8_t senDataEnable = 0;

#ifdef TLSR8258_DK48

#define KEY_TYPE_NONE      0x00
#define KEY_TYPE_KEYBOARD  0x01
#define KEY_TYPE_CONSUME   0x02

static uint8_t  keyType     = KEY_TYPE_NONE;
static uint8_t  keyPressed  = false;
static uint32_t keyScanTick = 0;

void App_KeyInit(void)
{
	KB_Init();
}

void App_KeyChangeHandler(void)
{
	uint8_t  key0 = kbCb.keyCode[0];
	uint16_t consumerKey = 0;
	uint8_t  keyboard[8]={0};

	keyPressed = true;

	switch(kbCb.cnt)
	{
	case 0://key release
		//TRACK_INFO("key release...\r\n");

		keyPressed = false;
		if(keyType & KEY_TYPE_CONSUME){
			App_SendKeyReport(HID_INPUT_REPORT_2_HDL, (uint8_t*)&consumerKey, 2);
		}
		if(keyType & KEY_TYPE_KEYBOARD){
			App_SendKeyReport(HID_INPUT_REPORT_1_HDL, (uint8_t*)&keyboard, 8);
		}
		keyType = KEY_TYPE_NONE;

		break;

	case 1:// one key pressed
		//TRACK_INFO("1 key pressed...\r\n");

		if(key0 == CR_VOL_UP){
			consumerKey = MKEY_VOL_UP;
			senDataEnable = true;
		}else if(key0 == CR_VOL_DN){
			consumerKey = MKEY_VOL_DN;
			senDataEnable = false;
		}else if(key0 == BTN_PAIR){
			keyboard[2] = 0x1e;
		}else if(key0 == BTN_UNPAIR){
			keyboard[2] = 0x1f;
		}

		if(key0 == CR_VOL_UP || key0 == CR_VOL_DN){
			keyType |= KEY_TYPE_CONSUME;
		}else if(key0 == BTN_PAIR || key0 == BTN_UNPAIR){
			keyType |= KEY_TYPE_KEYBOARD;
		}else{
			keyType = KEY_TYPE_NONE;
		}

		if(keyType & KEY_TYPE_CONSUME){
			App_SendKeyReport(HID_INPUT_REPORT_2_HDL, (uint8_t*)&consumerKey, 2);
		}else if(keyType & KEY_TYPE_KEYBOARD){
			App_SendKeyReport(HID_INPUT_REPORT_1_HDL, (uint8_t*)&keyboard, 8);
		}
		break;

	case 2://two key pressed
		//TRACK_INFO("2 key pressed...kbCb.keyCode[0]:0x%02x,kbCb.keyCode[1]:0x%02x\r\n", kbCb.keyCode[0], kbCb.keyCode[1]);
		break;

	default:
		break;
	}
}

void App_KeyTaskStart(void)
{
	if(!SysTimer_IsTimeExpired(keyScanTick, 20 * 1000)){  //keyScan interval: 20mS
		return;
	}
	keyScanTick = SysTimer_GetCurTick();

	bool_t keyChanged = KB_Scan();

	if(keyChanged){
		App_KeyChangeHandler();
	}
}
#else
static uint8_t  keyPressed  = false;
static uint8_t  keyValid = false;
void App_KeyInit(void)
{
	Btn_Init();
}

void App_KeyChangeHandler(void)
{
	BtnData_t *pBtnData = Btn_GetData();

	uint16_t consumerKey = 0;
	keyPressed = true;

	switch(pBtnData->cnt)
	{
	case 0:
		if(keyValid){
			keyValid = false;
			App_SendKeyReport(HID_INPUT_REPORT_2_HDL, (uint8_t*)&consumerKey, 2);
		}
		break;

	case 1:
		if(pBtnData->code[0] == BTN_PAIR){
			consumerKey = MKEY_VOL_DN;
			APP_TRACK_INFO("Vol- \r\n");

			senDataEnable = true;
		}
		else if(pBtnData->code[0] == BTN_UNPAIR){
			consumerKey = MKEY_VOL_UP;
			APP_TRACK_INFO("Vol+ \r\n");

			senDataEnable = false;
		}
		if(consumerKey){
			keyValid = true;
			App_SendKeyReport(HID_INPUT_REPORT_2_HDL, (uint8_t*)&consumerKey, 2);
		}
		break;

	case 2:
		break;

	default:
		break;
	}
}

void App_KeyTaskStart(void)
{
	static uint32_t keyScanTick = 0;
	if(!SysTimer_IsTimeExpired(keyScanTick, 20 * 1000)){  //keyScan interval: 20mS
		return;
	}
	keyScanTick = SysTimer_GetCurTick();

	bool_t keyChanged = Btn_Scan();
	if(keyChanged)
	{
		App_KeyChangeHandler();
	}
}
#endif /* End of TLSR8258_DK48 */

/******************************************************************************/
/* Event Call-back                                                            */
/******************************************************************************/
uint32_t A_createConnStart = 0;
uint32_t A_connHandle = 0xFFFF;
uint32_t sendDataTick = 0;

void DM_EvtHandler(DmEvt_t *pEvt)
{
	switch(pEvt->hdr.event)
	{
	case DM_ADV_REPORT_IND:
		break;

	case DM_CONN_OPEN_IND:
		APP_TRACK_INFO("****** Connection Cmpl ******\r\n\t"
				       "-connHandle:%d\r\n\t"
					   "-role:%s\r\n\t"
					   "-addr_type:%d\r\n\t"
				       "-peer_addr: ",
					   pEvt->leConnCmpl.handle,
					   pEvt->leConnCmpl.role == DM_ROLE_MASTER ? "Master": "Slave",
					   pEvt->leConnCmpl.peerAddrType);
		TRACK_DATA((uint8_t*)&pEvt->leConnCmpl.peerAddr, 6);

	#if !APP_PM_EN
		BSP_LedOn(LED_RED_PIN);
		BSP_LedOff(LED_WHITE_PIN);//MIC failed flag
		BSP_LedOff(LED_GREEN_PIN);//timeout flag
	#endif
		A_createConnStart = SysTimer_GetCurTick()|1;
		A_connHandle = pEvt->leConnCmpl.handle;

		APP_AllocCcb(pEvt->leConnCmpl.handle, pEvt->leConnCmpl.role);
		break;

	case DM_CONN_CLOSE_IND:
		APP_TRACK_INFO("Disconnection Cmpl:\r\n\t-connHandle: 0x%02x\r\n\t-reason:0x%02x\r\n",
				        pEvt->disconnectCmpl.handle, pEvt->disconnectCmpl.reason);

	#if !APP_PM_EN
		BSP_LedOff(LED_RED_PIN);
		if(pEvt->disconnectCmpl.reason == HCI_ERR_CONN_TERM_MIC_FAILURE){//mic failed
			BSP_LedOn(LED_WHITE_PIN);
		}
		else if(pEvt->disconnectCmpl.reason == HCI_ERR_CONN_TIMEOUT){//timeout
			BSP_LedOn(LED_GREEN_PIN);
		}
	#endif

		A_createConnStart = 0;
		sendDataTick = 0;
		A_connHandle = 0xFFFF; // invalid connection handle.
		A_rx_pkt_cnt = 0;
		A_tx_pkt_cnt = 0;

		APP_ReleaseCcbByHandle(pEvt->disconnectCmpl.handle);

		DM_LE_SetAdvEnable(ENABLE);
		break;

	case DM_CONN_CH_SEL_IND:
		APP_TRACK_INFO("Chn Select cmpl\r\n\t-CSA: %d\r\n", pEvt->leChnSelInd.chSelAlg);
		break;

	case DM_CONN_PHY_UPD_IND:
		APP_TRACK_INFO("Phy upd cmpl\r\n\t-Phy: %d\r\n", pEvt->lePhyUpdCmpl.txPhy);
		break;

	case DM_CONN_UPD_IND:
		APP_TRACK_INFO("Conn Upd Cmpl:\r\n\t-intvl:%d us\r\n\t-latency:%d\r\n\t-to:%d ms\r\n",
				       pEvt->leConnUpdateCmpl.connInterval *UNIT_1_25_MS,
					   pEvt->leConnUpdateCmpl.connLatency,
				       pEvt->leConnUpdateCmpl.supTimeout * 10);
		break;

	case DM_CONN_DATA_LEN_CHANGE_IND:
		APP_TRACK_INFO("LE data length changed\r\n\t-max tx: %d B\r\n\t-max rx: %d B\r\n",
				       pEvt->leDataLenChange.maxTxOctets, pEvt->leDataLenChange.maxRxOctets);
		break;

	case DM_SMP_PAIR_END_IND:
		if(pEvt->smpPairEndInd.status){
			APP_TRACK_INFO("Pair failed...connHandle: 0x%02x\r\n", pEvt->smpPairEndInd.connHandle);
		}
		else{
			APP_TRACK_INFO("Pair successfully...connHandle: 0x%02x\r\n", pEvt->smpPairEndInd.connHandle);
			AppCCB_t *pCcb = APP_GetConnCb(pEvt->smpPairEndInd.connHandle);
			if(pCcb){
				pCcb->isSmpCmpl = true;
			}
		}
		break;

	case DM_SMP_PIN_CODE_IND:
		APP_TRACK_INFO("connHandle:%d, Pin_Code:%06d\r\n",pEvt->smpPinCodeInd.connHandle, pEvt->smpPinCodeInd.pinCode);
		break;

	case DM_SMP_PIN_CODE_REQ:
	{
		uint32_t pinCode = 123456;
		SMP_SetPinCode(pEvt->smpPinCodeReq.connHandle, pinCode);
		APP_TRACK_INFO("%6d\r\n", pinCode);
		break;
	}

	default:
		break;
	}
}

void ATT_EvtHandler(AttEvt_t *pEvt)
{
	switch(pEvt->hdr.event)
	{
	case ATT_MTU_UPDATE_IND:
		APP_TRACK_INFO("MTU Upd Cmpl\r\n\t-MTU:%d B\r\n", pEvt->mtu);
		break;

	case ATTS_CCC_STATE_IND:
		break;

	case ATTS_HANDLE_VALUE_CNF:
		APP_TRACK_INFO("ATT Handle Value Confirm\r\n");
		break;

	default:
		break;
	}
}

void APP_Init(void)
{
	appCb.handlerId = MDC_AddMsgHandler(APP_MsgHandler);

#if APP_LED_EN && !APP_PM_EN
	appCb.timer.handlerId = appCb.handlerId;
	appCb.timer.msg.event = APP_EVT_UPD_ADV_DATA;
	MDC_TimerStartMs(&appCb.timer, LED_BLINK_PERIOD);
#endif

	App_KeyInit();
}

void APP_Start(void)
{
	App_KeyTaskStart();
}

void Setup(void)
{
	/* memory initialization. */
	lg_mem_init();
	HeapInit((uint8_t *)&heap[0], APP_HEAP_MEM_SIZE);

	/* KV initialization. */
	kv_init(CFG_KV_FLASH_BASE_ADDR, CFG_KV_BLOCK_SIZE, CFG_KV_BLOCK_NUM);

	/* BSP initialization. */
	BSP_InitAllLed();

	/* Buffer pool alloc. */
	pool_desc_t pools[] ={
		{16,     8 },
		{32,     8 },
		{80,     4 },
	    {280,    4 },
	};
	PoolBufInit(pools, COUNTOF(pools));

	/* MDC system initialization. */
	MDC_Init();

	/* MDC Timer initialization. */
	MDC_TimerInit();

	/* Set MAC address. */
	uint8_t bdAddr[6] = {0x66, 0x66, 0x66, 0x66, 0x00, 0x00};
	GetConfigParam(CFG_PARAM_MAC_ADDR, bdAddr, 6);
	LL_SetBdAddr(bdAddr, BD_ADDR_LEN);

	APP_TRACK_INFO("BD_ADDR:");
	APP_TRACK_DAT(bdAddr, BD_ADDR_LEN);

	/* LL initialization. */
	LL_Init(&llCfg);
	LL_SlvInit();
	BB_SetTxPower(BB_POWER_P3p01_dBm);

	hostCfg.numMaxConn = APP_MAX_CONN_NUM;

	/* HCI initialization. */
	HCI_Init();
	HCI_SetMaxAclLen(247 + 4);/*!< Set L2CAP payload size= 104B ==> ATT MTU Size = 100. */

	/* DM initialization. */
	DM_Init();
	DM_AdvInit();
	DM_SecInit();
	DM_EvtRegister(DM_EvtHandler);
	DM_SecSetInitiateSecEnable(true);
	//DM_SecSetIoCap(IO_CAP_DISPLAY_ONLY);
	//DM_SecSetAuth(SMP_AUTH_BOND_FLAG | SMP_AUTH_MITM_FLAG);
	//DM_SecSetKeyDist(SMP_ENCKEY);
	//DM_SecSetDefPinCode(123456, ENABLE);

	/* L2CAP initialization. */
	L2C_Init();
	L2C_SlvInit();

	/* ATT initialization. */
	ATT_Init();
	ATT_EvtRegister(ATT_EvtHandler);
	ATTS_Init();
	ATTS_CccRegister(&ServerCccSets[0], CCC_IDX_MAX, NULL);

	/* Register GATT services */
	ATTS_AddAttGroup(&gapGrp);
	ATTS_AddAttGroup(&gattGrp);
	ATTS_AddAttGroup(&battGrp);
	ATTS_AddAttGroup(&hidGrp);
	ATTS_AddAttGroup(&gwGrp);
	ATTS_AddAttGroup(&htsGrp);

	/* SMP initialization. */
#if 0
	SMP_NonInit();
#else
	SMP_Init();
	SMP_RespInit();
#endif

	/* ADV initialization. */
	DM_LE_SetAdvParam(APP_ADV_INTR_MIN,        /*!< min adv interval.   */
			          APP_ADV_INTR_MAX,        /*!< max adv interval.   */
			          APP_ADV_EVT_TYPE,        /*!< adv event type.     */
			          APP_ADV_LOCAL_ADDR_TYPE, /*!< local address type. */
			          APP_ADV_PEER_ADDR_TYPE,  /*!< peer address type.  */
			          NULL,                    /*!< peer address.       */
			          APP_ADV_CHN,             /*!< adv channel map.    */
			          APP_ADV_FILT);           /*!< adv filter policy.  */

	uint8_t advData[] = {
		0x02, 0x01, 0x06,         /*!< Flag type.  */
		0x04, 0x08, 'H','I','D',  /*!< short name. */
		0x03, 0x19, 0x80, 0x01,   /*!< 384, Generic Remote Control, Generic category */
		0x03, 0x02, 0x12, 0x18,   /*!< service UUID */
	};
	uint8_t scanRsp[] = {
		0x04, 0x09, 'H','I','D',  /*!< complete name. */
	};
	DM_LE_SetAdvData(advData, sizeof(advData));
	DM_LE_SetScanRspData(scanRsp, sizeof(scanRsp));
	DM_LE_SetAdvEnable(ENABLE);

	/* PM initialization. */
#if APP_PM_EN
	LL_PmInit(NULL, ENABLE);
#endif

	/* Application initialization. */
	APP_Init();
}

#if 0
uint8_t data1[] = {//51, 0x00, 0x04, 0x00, 0x1B, 26, 0x00,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,//80

	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,//80

	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,//80

	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,//80
};
#endif

uint32_t A_loop=0;
void Loop(void)
{
	A_loop++;

	MDC_Start();

	APP_Start();

	if(A_createConnStart && SysTimer_IsTimeExpired(A_createConnStart, 6000*1000))
	{
		A_createConnStart = 0;
		sendDataTick = SysTimer_GetCurTick();

	#if 0
		HID_MouseTestReset();
	#endif
	}

#if 0
	if(A_connHandle != 0xFFFF && sendDataTick && IsTimeExpired(sendDataTick, 6000)){
		HID_MoueTestStart(A_connHandle);
		sendDataTick = GetCurSysTick()|1;
	}
#endif

#if APP_PM_EN
	PM_SleepStart();
#endif
}

